package algorithm;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

import connection.Session;

/**
 * 
 * @author Julian Beisert
 * @version 1.0
 */
public class TAN {

	private HashMap<String, HashMap<String, String>> _tan;
	private static TAN _instance;

	private TAN() {

	}

	/**
	 * 
	 * @return External IP
	 */
	private String getExternalIp() {
		URL whatismyip = null;
		String ip = null;
		try {
			whatismyip = new URL("http://checkip.amazonaws.com");
		} catch (MalformedURLException e1) {
			e1.printStackTrace();
		}
		BufferedReader in = null;
		try {
			in = new BufferedReader(new InputStreamReader(
					whatismyip.openStream()));
			ip = in.readLine();
			return ip;
		} catch (IOException e) {
			e.printStackTrace();
			ip = "0.0.0.0";
		} finally {

			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return ip;
	}

	/**
	 * 
	 * @return Local IP
	 */
	private String getLocalIp() {
		String localIp = null;
		try {
			localIp = InetAddress.getLocalHost().getHostAddress();
			return localIp;
		} catch (UnknownHostException e) {
			e.printStackTrace();
			localIp = "0.0.0.0";
		}
		return localIp;
	}

	/**
	 * 
	 * @param IP
	 *            IP Address represented as String
	 * @return
	 */
	private String generateTanFromIP(String IP) {
		Session session = Session.getInstance();
		String sessionBit = String.valueOf(session.getServerSession());

		String tan;
		String[] tanArray = IP.split("\\.", 4);

		String first8Bit = tanArray[0];
		if (first8Bit.length() == 2) {
			char[] first8BitArray = new char[3];
			first8BitArray[0] = ':';
			first8BitArray[1] = first8Bit.charAt(0);
			first8BitArray[2] = first8Bit.charAt(1);
			first8Bit = String.copyValueOf(first8BitArray);
		} else if (first8Bit.length() == 1) {
			char[] first8BitArray = new char[3];
			first8BitArray[0] = ':';
			first8BitArray[1] = first8Bit.charAt(0);
			first8BitArray[2] = ':';
			first8Bit = String.copyValueOf(first8BitArray);
		}

		String second8Bit = tanArray[1];
		if (second8Bit.length() == 2) {
			char[] second8BitArray = new char[3];
			second8BitArray[0] = ':';
			second8BitArray[1] = second8Bit.charAt(0);
			second8BitArray[2] = second8Bit.charAt(1);
			second8Bit = String.copyValueOf(second8BitArray);
		} else if (second8Bit.length() == 1) {
			char[] second8BitArray = new char[3];
			second8BitArray[0] = ':';
			second8BitArray[1] = second8Bit.charAt(0);
			second8BitArray[2] = ':';
			second8Bit = String.copyValueOf(second8BitArray);

		}

		String third8Bit = tanArray[2];
		if (third8Bit.length() == 2) {
			char[] third8BitArray = new char[3];
			third8BitArray[0] = ':';
			third8BitArray[1] = third8Bit.charAt(0);
			third8BitArray[2] = third8Bit.charAt(1);
			third8Bit = String.copyValueOf(third8BitArray);
		} else if (third8Bit.length() == 1) {
			char[] third8BitArray = new char[3];
			third8BitArray[0] = ':';
			third8BitArray[1] = third8Bit.charAt(0);
			third8BitArray[2] = ':';
			third8Bit = String.copyValueOf(third8BitArray);

		}
		String fourth8Bit = tanArray[3];
		if (fourth8Bit.length() == 2) {
			char[] fourth8BitArray = new char[3];
			fourth8BitArray[0] = ':';
			fourth8BitArray[1] = fourth8Bit.charAt(0);
			fourth8BitArray[2] = fourth8Bit.charAt(1);
			fourth8Bit = String.copyValueOf(fourth8BitArray);
		} else if (fourth8Bit.length() == 1) {
			char[] fourth8BitArray = new char[3];
			fourth8BitArray[0] = ':';
			fourth8BitArray[1] = fourth8Bit.charAt(0);
			fourth8BitArray[2] = ':';
			fourth8Bit = String.copyValueOf(fourth8BitArray);

		}

		tan = sessionBit.substring(0, 2) + first8Bit.substring(0, 1)
				+ third8Bit.substring(2, 3) + fourth8Bit.substring(0, 1)
				+ second8Bit.substring(0, 1) + first8Bit.substring(1, 2)
				+ fourth8Bit.substring(1, 2) + third8Bit.substring(0, 1)
				+ second8Bit.substring(1, 2) + first8Bit.substring(2, 3)
				+ fourth8Bit.substring(2, 3) + third8Bit.substring(1, 2)
				+ second8Bit.substring(2, 3) + sessionBit.substring(2, 4);
		return tan;
	}

	/**
	 * initialize TAN LAN/WAN Pair
	 */
	private void initializeTAN() {
		// initialize TAN LAN/WAN Pair HashMap
		_tan = new HashMap<String, HashMap<String, String>>();
		// create LAN TAN
		HashMap<String, String> lanTan = new HashMap<String, String>();
		String localIP = getLocalIp();
		String lanStringTan;
		if (localIP == "0.0.0.0") {
			lanStringTan = "keine Verbindung";
		} else {
			lanStringTan = generateTanFromIP(localIP);
		}

		lanTan.put(lanStringTan, localIP);

		// create WAN TAN
		HashMap<String, String> wanTan = new HashMap<String, String>();
		String externalIP = getExternalIp();
		String wanStringTan;
		if (externalIP == "0.0.0.0") {
			wanStringTan = "keine Verbindung";
		} else {
			wanStringTan = generateTanFromIP(externalIP);
		}

		wanTan.put(wanStringTan, externalIP);

		// populate TAN HashMap
		_tan.put("LAN", lanTan);
		_tan.put("WAN", wanTan);

	}

	/**
	 * 
	 * @param tan
	 *            TAN as String received from connection partner
	 * @return IP Address from TAN
	 */
	public String getIPFromTan(String tan) {
		Session session = Session.getInstance();
		String clientSessionString = tan.substring(0, 2)
				+ tan.substring(14, 16);
		Integer clientSession = Integer.valueOf(clientSessionString);
		session.setClientSession(clientSession);

		String IP = "";
		if (tan.charAt(2) == ':' && tan.charAt(10) == ':') {
			String first8Bit = String.valueOf(tan.charAt(6));
			IP += first8Bit;
		} else if (tan.charAt(2) == ':') {
			char[] first8BitArray = new char[2];
			first8BitArray[0] = tan.charAt(6);
			first8BitArray[1] = tan.charAt(10);
			String first8Bit = String.copyValueOf(first8BitArray);
			IP += first8Bit;
		} else {
			char[] first8BitArray = new char[3];
			first8BitArray[0] = tan.charAt(2);
			first8BitArray[1] = tan.charAt(6);
			first8BitArray[2] = tan.charAt(10);
			String first8Bit = String.copyValueOf(first8BitArray);
			IP += first8Bit;
		}

		if (tan.charAt(5) == ':' && tan.charAt(13) == ':') {
			String second8Bit = String.valueOf(tan.charAt(9));
			IP = IP + "." + second8Bit;
		} else if (tan.charAt(5) == ':') {
			char[] second8BitArray = new char[2];
			second8BitArray[0] = tan.charAt(9);
			second8BitArray[1] = tan.charAt(13);
			String second8Bit = String.copyValueOf(second8BitArray);
			IP = IP + "." + second8Bit;
		} else {
			char[] second8BitArray = new char[3];
			second8BitArray[0] = tan.charAt(5);
			second8BitArray[1] = tan.charAt(9);
			second8BitArray[2] = tan.charAt(13);
			String second8Bit = String.copyValueOf(second8BitArray);
			IP = IP + "." + second8Bit;
		}

		if (tan.charAt(8) == ':' && tan.charAt(3) == ':') {
			String third8Bit = String.valueOf(tan.charAt(12));
			IP = IP + "." + third8Bit;
		} else if (tan.charAt(8) == ':') {
			char[] third8BitArray = new char[2];
			third8BitArray[0] = tan.charAt(12);
			third8BitArray[1] = tan.charAt(3);
			String third8Bit = String.copyValueOf(third8BitArray);
			IP = IP + "." + third8Bit;
		} else {
			char[] third8BitArray = new char[3];
			third8BitArray[0] = tan.charAt(8);
			third8BitArray[1] = tan.charAt(12);
			third8BitArray[2] = tan.charAt(3);
			String third8Bit = String.copyValueOf(third8BitArray);
			IP = IP + "." + third8Bit;
		}

		if (tan.charAt(4) == ':' && tan.charAt(11) == ':') {
			String fourth8Bit = String.valueOf(tan.charAt(7));
			IP = IP + "." + fourth8Bit;
		} else if (tan.charAt(4) == ':') {
			char[] fourth8BitArray = new char[2];
			fourth8BitArray[0] = tan.charAt(7);
			fourth8BitArray[1] = tan.charAt(11);
			String fourth8Bit = String.copyValueOf(fourth8BitArray);
			IP = IP + "." + fourth8Bit;
		} else {
			char[] fourth8BitArray = new char[3];
			fourth8BitArray[0] = tan.charAt(4);
			fourth8BitArray[1] = tan.charAt(7);
			fourth8BitArray[2] = tan.charAt(11);
			String fourth8Bit = String.copyValueOf(fourth8BitArray);
			IP = IP + "." + fourth8Bit;
		}

		return IP;
	}

	/**
	 * 
	 * @return local TAN
	 */
	public String getLocalTAN() {
		HashMap<String, String> lan = new HashMap<String, String>();
		Set<String> key;
		Iterator<String> iter;

		lan = this._tan.get("LAN");
		key = lan.keySet();

		iter = key.iterator();

		String tan = null;

		while (iter.hasNext()) {
			tan = iter.next();
		}

		return tan;
	}

	/**
	 * 
	 * @return external TAN
	 */
	public String getExternalTAN() {
		HashMap<String, String> wan = new HashMap<String, String>();
		Set<String> key;
		Iterator<String> iter;

		wan = this._tan.get("WAN");
		key = wan.keySet();

		iter = key.iterator();

		String tan = null;

		while (iter.hasNext()) {
			tan = iter.next();
		}

		return tan;
	}

	/**
	 * 
	 * @return Singleton TanAlgorithm Object
	 */
	public static TAN getInstance() {
		if (_instance == null) {
			_instance = new TAN();
			_instance.initializeTAN();
			;
		}
		return _instance;

	}

}
